package com.maimao.user.service.sys;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.maimao.core.constant.Constants;
import com.maimao.core.enums.RespCode;
import com.maimao.core.exception.MaiMaoDaoException;
import com.maimao.core.model.resp.PageResult;
import com.maimao.core.model.resp.Result;
import com.maimao.core.utils.DateUtils;
import com.maimao.model.user.input.SysUserByResourceInput;
import com.maimao.model.user.sys.dto.DelDto;
import com.maimao.model.user.sys.vo.SysUserForm;
import com.maimao.user.mapper.sys.DepartmentMapper;
import com.maimao.model.user.sys.Department;
import com.maimao.model.user.sys.Resources;
import com.maimao.model.user.sys.Role;
import com.maimao.model.user.sys.SysUser;
import com.maimao.model.user.sys.dto.SysUserSearchInput;
import com.maimao.model.user.sys.vo.Permissions;
import com.maimao.user.mapper.sys.ResourcesMapper;
import com.maimao.user.mapper.sys.RoleMapper;
import com.maimao.user.mapper.sys.SysUserMapper;
import com.maimao.model.user.sys.vo.SysUserVo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

import static com.maimao.core.constant.Constants.ONE;

/**
 * @author MaoLin Wang
 * @date 2020/11/30 9:17 下午
 */
@Service
public class SysUserService {

    private Log log = LogFactory.get(SysUserService.class);

    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private RoleMapper roleMapper;

    @Autowired
    private ResourcesMapper resourcesMapper;

    @Autowired
    private DepartmentMapper departmentMapper;

    @Autowired
    private BCryptPasswordEncoder bCryptPasswordEncoder;


    /**
     * 根据用户id查询权限信息
     *
     * @param userId
     * @return
     */
    public Permissions getPermissions(Integer userId) {
        SysUser sysUser = sysUserMapper.selectByIdCus(userId);
        if (sysUser == null) {
            return null;
        }
        Permissions permissions = getPermissions(sysUser);
        return permissions;
    }

    public Permissions getPermissions(String username) {
        SysUser sysUser = sysUserMapper.selectByUsernameValid(username);
        if (sysUser == null) {
            return null;
        }
        Permissions permissions = getPermissions(sysUser);
        return permissions;
    }


    private Permissions getPermissions(SysUser sysUser) {
        Permissions permissions = new Permissions();
        permissions.setId(Long.valueOf(sysUser.getId()));
        permissions.setAvatar(sysUser.getPicture());
        permissions.setUsername(sysUser.getUsername());
        permissions.setRealName(sysUser.getRealName());
        permissions.setPassword(sysUser.getPassword());

        List<Role> roles = sysUser.getRoleList();
        if (roles != null && roles.size() > 0) {
            List<String> roleNames = roles.stream().map(Role::getRoleCode).collect(Collectors.toList());
            List<Integer> roleIds = roles.stream().map(Role::getId).collect(Collectors.toList());

            permissions.setRoles(roleNames);
            List<Resources> resourcesList = resourcesMapper.selectByRoleIdBatch(roleIds);
            if (resourcesList != null && resourcesList.size() > 0) {
                List<String> resourcesNames = resourcesList.stream().map(Resources::getCode).collect(Collectors.toList());
                permissions.setResources(resourcesNames);
            }
        }
        return permissions;
    }

    public List<SysUser> findByName(String name) {
        List<SysUser> sysUsers = sysUserMapper.selectByNameLike(name);
        return sysUsers;
    }

    /**
     * 分页条件查询后台用户
     */
    public PageResult<SysUserVo> search(Integer page, Integer size, SysUserSearchInput input) {
        List<Integer> departmentIds = input.getDepartmentIds();
        String path = null;
        if (departmentIds != null && departmentIds.size() > 0) {
            path = StringUtils.join(departmentIds, Constants.UNDER_LINE);
        }
      /*  QueryWrapper<SysUser> wrapper = new QueryWrapper<SysUser>()
                .select("id", "real_name", "username", "status", "email", "create_time", "department_id")
                .likeRight(!StringUtils.isEmpty(input.getMobile()), "mobile", input.getMobile())
                .like(!StringUtils.isEmpty(input.getRealName()), "real_name", input.getRealName())
                .eq(input.getStatus() != null && !input.getStatus().equals(Constants.STATUS_ALL), "status", input.getStatus())
                .eq(path != null, "department_path", path)
                .eq("1", 1);*/

        PageHelper.startPage(page, size);
        List<SysUser> sysUsers = sysUserMapper.selectByParam(input.getRealName(), input.getMobile(), input.getStatus(), path);
        if (sysUsers != null && sysUsers.size() > 0) {
            PageInfo<SysUser> pageInfo = new PageInfo(sysUsers);

            List<SysUserVo> vos = new ArrayList<>(sysUsers.size());

            SysUserVo vo = null;
            for (SysUser sysUser : pageInfo.getList()) {
                vo = new SysUserVo();
                vo.setCreateTime(sysUser.getCreateTime());
                vo.setEmail(sysUser.getEmail());
                vo.setId(sysUser.getId());
                vo.setRealName(sysUser.getRealName());
                vo.setStatus(sysUser.getStatus());
                vo.setUsername(sysUser.getUsername());
                List<Role> roleList = sysUser.getRoleList();
                if (roleList != null && roleList.size() > 0) {
                    List<Integer> roleIds = roleList.stream().map(Role::getId).collect(Collectors.toList());
                    vo.setRoleIds(roleIds);
                }

                if (!StringUtils.isEmpty(path)) {
                    //如果path存在，则到这里根据该条件是有结果的，且sysUsers的部门path都为path
                    getDepartmentPathName(departmentIds, vo);
                } else {
                    //没有选择部门
                    Department department = departmentMapper.selectOne(new QueryWrapper<Department>().select("id", "path").eq("id", sysUser.getDepartmentId()));
                    if (department != null) {
                        String dpath = department.getPath();
                        if (!StringUtils.isEmpty(dpath)) {
                            String[] pathStr = StringUtils.split(dpath, Constants.UNDER_LINE);
                            List<Integer> paths = new ArrayList<>(pathStr.length);
                            for (String p : pathStr) {
                                paths.add(Integer.valueOf(p));
                            }
                            getDepartmentPathName(paths, vo);
                        }
                    }
                }
                vos.add(vo);
            }
            return new PageResult<SysUserVo>(vos, pageInfo.getTotal());
        }
        return new PageResult<SysUserVo>(Collections.emptyList());

    }

    private void getDepartmentPathName(Collection<Integer> departmentIds, SysUserVo vo) {
        List<Department> departments = departmentMapper.selectList(new QueryWrapper<Department>()
                .select("id", "name")
                .in("id", departmentIds));
        if (departments != null && departments.size() > 0) {
            List<String> departmentNames = departments.stream().map(Department::getName).collect(Collectors.toList());
            List<Integer> dids = departments.stream().map(Department::getId).collect(Collectors.toList());
            vo.setDepartmentNames(StringUtils.join(departmentNames, Constants.MIDDLE_LINE));
            vo.setDepartmentIds(dids);
        }
    }

    /**
     * 注册新员工（只包含基本信息）
     *
     * @param sysUserForm
     * @return
     */
    @Transactional(rollbackFor = MaiMaoDaoException.class)
    public Result add(SysUserForm sysUserForm) {
        SysUser exist = sysUserMapper.selectByUsernameSimple(sysUserForm.getUsername());
        if (exist != null) {
            return Result.notValid("用户名已存在");
        }

        SysUser sysUser = userForm2SysUser(sysUserForm);
        sysUser.setStatus(Constants.STATUS_1);
        sysUser.setCreateTime(DateUtils.now());
        sysUser.setLeader(Constants.STATUS_0);
        //默认密码为用户名
        sysUser.setPassword(bCryptPasswordEncoder.encode(sysUser.getUsername()));
        int count = sysUserMapper.insert(sysUser);
        if (count > 0) {
            List<Integer> roleIds = sysUserForm.getRoleIds();
            if (roleIds != null && roleIds.size() > 0) {
                List<Role> roles = roleMapper.selectList(new QueryWrapper<Role>().select("id", "sys_role").eq("status", Constants.STATUS_1).in("id", roleIds));
                if (roles != null && roles.size() > 0) {
                    for (Role role : roles) {
                        if (!Constants.STATUS_1.equals(role.getSysRole())) {
                            //分配了非后台角色
                            return Result.notValid("请分配后台角色");
                        }
                    }
                } else {
                    return Result.notValid("角色不存在或已冻结，请重新选择");
                }
                sysUserMapper.addUserRoleRecord(Long.valueOf(sysUser.getId()), roleIds);
            }
        }
        return Result.ok(RespCode.OK, "添加成功");
    }


    /**
     * 更新用户基本信息
     *
     * @param sysUserForm
     * @return
     */
    @Transactional(rollbackFor = MaiMaoDaoException.class)
    public Result<Void> update(SysUserForm sysUserForm) {
        if (sysUserForm.getUsername() != null) {
            sysUserForm.setUsername("");
        }

        SysUser sysUser = userForm2SysUser(sysUserForm);
        sysUser.setUpdateTime(DateUtils.now());
        sysUserMapper.updateCus(sysUser);
        List<Integer> roleIds = sysUserForm.getRoleIds();
        if (roleIds != null && roleIds.size() > 0) {
            List<Role> roles = roleMapper.selectList(new QueryWrapper<Role>().select("id", "sys_role").eq("status", Constants.STATUS_1).in("id", roleIds));
            if (roles != null && roles.size() > 0) {
                for (Role role : roles) {
                    if (!Constants.STATUS_1.equals(role.getSysRole())) {
                        //分配了非后台角色
                        return Result.notValid("不可分配前台角色");
                    }
                }
            } else {
                return Result.notValid("角色不存在或已冻结，请重新选择");
            }
            sysUserMapper.deleteRecordBatch(sysUser.getId());
            sysUserMapper.addUserRoleRecord(Long.valueOf(sysUser.getId()), roleIds);
        }
        return Result.ok(RespCode.OK, "修改成功");
    }

    /**
     * 转为SysUser
     *
     * @param sysUserForm
     * @return
     */
    private SysUser userForm2SysUser(SysUserForm sysUserForm) {
        if (sysUserForm == null) {
            return null;
        }
        SysUser.SysUserBuilder builder = SysUser.builder()
                .id(sysUserForm.getId())
                .username(sysUserForm.getUsername())
                .realName(sysUserForm.getRealName())
                .updateTime(DateUtils.now());

        List<Integer> departmentIds = sysUserForm.getDepartmentIds();
        if (departmentIds != null && departmentIds.size() > 0) {
            String path = StringUtils.join(departmentIds, Constants.UNDER_LINE);

            builder.departmentId(departmentIds.get(departmentIds.size() - 1));
            builder.departmentPath(path);
        }

        return builder.build();


    }

    private void updateCommon(SysUser sysUser) {
      /*  UpdateWrapper<SysUser> updateWrapper = new UpdateWrapper<>();
        updateWrapper.set(notNullOrBlank(sysUser.getRealName()),"real_name",sysUser.getRealName())
                .set(notNullOrBlank(sysUser.getWx()),"wx",sysUser.getWx())
                .set(notNullOrBlank(sysUser.getIdNumber()),"id_number",sysUser.getIdNumber())
                .set(sysUser.getStatus()!=null,"status",sysUser.getStatus())
                .set(sysUser.getDepartmentId()!=null & sysUser.getDepartmentId()>0,"department_id",sysUser.getDepartmentId())
                .set(notNullOrBlank(sysUser.getDepartmentPath()),"department_path",sysUser.getDepartmentPath())
                .set(sysUser.getBirthday()!=null,"birthday",sysUser.getBirthday())
                .set(sysUser.getCreateTime()!=null,"create_time",sysUser.getCreateTime())
                .set(sysUser.getUpdateTime()!=null,"update_time",sysUser.getUpdateTime())
                .eq("id",sysUser.getId());*/
    }

    private boolean notNullOrBlank(String value) {
        return !StringUtils.isEmpty(value);
    }


    /**
     * 批量更新状态
     *
     * @param delDto
     */
    @Transactional(rollbackFor = MaiMaoDaoException.class)
    public void updateStatusBatch(DelDto delDto) {
        List<Integer> ids = delDto.getIds();
        Integer status = delDto.getStatus();
        sysUserMapper.updateStatusBatch(ids, status);
    }

    @Transactional(rollbackFor = MaiMaoDaoException.class)
    public void delete(Integer id) {
        int count = sysUserMapper.deleteById(id);
        if (count > 0) {
            sysUserMapper.deleteRecordBatch(id);
        }
    }

    /**
     * 重置密码
     *
     * @param id 用户id
     */
    @Transactional(rollbackFor = MaiMaoDaoException.class)
    public void reset(Integer id) {
        SysUser sysUser = sysUserMapper.selectByIdCus(id);
        if (sysUser != null) {
            sysUserMapper.updatePass(id, bCryptPasswordEncoder.encode(sysUser.getUsername()));
        }
    }

    public Set<Integer> queryByResource(SysUserByResourceInput input) {
        List<Integer> sysUserIds = sysUserMapper.queryByResourceIds(input.getResourcesIds());
        if (ObjectUtil.isNotEmpty(sysUserIds)) {
            if (sysUserIds.size() == ONE && sysUserIds.get(0).equals(ONE)) {
                //只有一个超管
                log.warn("商品审核负责人只有超管一个！请分配商品审核负责人");
            }
            if (ObjectUtil.isNull(input.getLimit()) || input.getLimit() <= 0) {
                return CollUtil.newHashSet(sysUserIds);
            }
            if (input.getLimit() > sysUserIds.size()) {
                input.setLimit(sysUserIds.size());
            }
            Set<Integer> res = RandomUtil.randomEleSet(sysUserIds, input.getLimit());
            return res;
        }
        return null;
    }
}
